Introduction#

Many client-server communication technologies have emerged over the years since the inception of the World Wide Web. Application programming interfaces (APIs) have further smoothed communication between clients and servers. In addition, coupled with emerging technologies, APIs have enabled the development of more complex applications. However, such advancements compelled API developers to invent newer methods for fetching data from the back-end servers due to the limitation of existing architectural styles. Although the preexisting REST APIs provide a scalable and flexible model for data transfer in the form of XML or JSON, they are insufficient to handle contemporary feature-rich and complex applications.

For example, today's social media applications like Facebook and Twitter fetch user data from multiple endpoints. Traditional architectural styles like the REST API prove inefficient for fetching data from multiple endpoints. Therefore, custom data-fetching solutions emerged with time. GraphQL is an example of such custom solutions. It was developed by Facebook to meet their exceeding data-fetching requirements.

REST versus GraphQL: Accessing multiple endpoints
REST versus GraphQL: Accessing multiple endpoints

This lesson will introduce GraphQL and specify the essential components in client-server communication using the same. However, before that, we’ll identify some of the limitations of REST architecture that paved the way for GraphQL.

REST API drawbacks#

In a REST API, we hit a URL and receive whatever data comes back. However, there are certain problems with how a REST API fetches data, as given below:

  • Multiple requests problem: A REST API sends multiple requests whenever data required by the application resides on multiple endpoints. There is a need for a mechanism to fetch data from multiple endpoints in a single request.

  • Overfetching and underfetching: Often, in a REST API, the data fetched in response to a single request is either a very large amount or a very small amount that does not serve the purpose of the application's request. Therefore, we need an approach to fetch the exact amount of data needed by an application.

Let's discuss these drawbacks in detail in the following sections.

Note: In this lesson, we’ll use SWAPI (Star Wars API) for demonstration purposes to convey better ideas of GraphQL to our learners.

Multiple requests problem#

In a REST API, we fetch different types of data from different access points (URLs), which often causes us to send various requests to fetch the desired data. For example, to access the starships, planets, and films data using SWAPI, we would need to make multiple requests to the respective endpoints:

  • For starships, we need to access the https://swapi.dev/api/starships/ endpoint.

  • For planets, we need to access the https://swapi.dev/api/planets/ endpoint.

  • For films, we need to access the https://swapi.dev/api/allFilms/ endpoint.

In the end, after the successful fetching of required data from multiple endpoints, the client starts rendering it.

Client
Client
Starships
Starships
Planets
Planets
Films
Films
Fetch starship data
Fetch starship data
Fetch planets data
Fetch planets data
Endpoints
Endpoi...
Browser starts rendering after fetching all the data
Browser starts rendering aft...
Fetch films data
Fetch films data
Viewer does not support full SVG 1.1
Fetching starships, planets, and films data using multiple requests

Overfetching and underfetching#

REST often suffers from two other types of problems: Overfetching and underfetching. Overfetching refers to retrieving extra information than what is needed, while underfetching is when the fetched information is not enough for an application. The problem with overfetching is that it uses extra resources and may burden a server with an additional load. Due to underfetching, the client makes more requests to the server to access the desired data.

For example, the following GET request returns a starship data having an ID equal to 10.

A REST request to the Star Wars API for the starship having ID=10

The response to the above GET request receives the following data in JSON format. For example, if we require just the name, length, and cargoCapacity, the GET request will instead return all the following data consisting of other attributes of the starship having an ID equal to 10.

An overfetching response to the GET request to the Star War REST API

The underfetching occurs when a specific URL doesn't provide the required information. In such cases, the clients make additional requests to fetch the required data. This can lead to the n+1n+1 requests problem, in which the client first downloads a list of endpoints and then makes one additional request per endpoint to fetch the required data. For example, if we need the pilots data of the Light freighter starship, the client will first download the following links and then make a request to each URL mentioned below:

Pilots endpoints of the Light freighter starship

Point to Ponder

Question

Can underfetching lead to issues like overburdening the server?

Hide Answer

Yes, like overfetching, underfetching can also overburden a server due to too many requests to get the desired data.

Both underfetching and overfetching cause issues. The extra round trips to get desired data increase latency. Also, sending too much data to the client, most of which the client throws away, is a waste of data and adds client-perceived latency that makes an application feel sluggish.

GraphQL was developed to address the above drawbacks in the REST API. In the rest of the lesson, we’ll discuss GraphQL and the way it resolves the problems that arise while using the REST API.

Emergence of GraphQL#

GraphQL is a new API standard and a query language specification developed by Facebook in 2012 to handle the problems in the REST APIs. Before making it open source in 2015, Facebook had used it internally as an alternative to the common REST architecture. GraphQL is analogous to the SQL queries in relational databases, where we can build a query to fetch the required data from multiple tables. GraphQL works in a similar way for APIs to fetch data from multiple endpoints in a single request.

Note: From a client's perspective, it will be a single request, but at the server side, we’ll probably need to make many round trips inside the data center to different components, like databases, caches, and so on. However, that isn’t bad because latency inside the data center is very low as compared to latency between client and server.

GraphQL is sometimes confused with the database, but it’s actually a query language for APIs. Therefore, it can be used in any context where an API can be used. GraphQL is also transport agnostic, just like REST, but it typically uses HTTP as the underlying protocol for its operations.

Components of GraphQL#

The implementation of GraphQL can be divided into two components: the GraphQL server and the GraphQL client. Let's discuss each component one by one.

The GraphQL server#

The GraphQL server takes our APIs and exposes them to the GraphQL client via an endpoint. It has two main parts:

  • Schema: A schema is a model of the data and defines relationships between the data. Based on the schema, the server specifies what types of queries and data a client can request.

  • Resolve functions: A schema can tell us what types of data a client can request but lacks information about where the data comes from. Here, the resolve functions specify how types and fields in the schema are connected to various backends. In other words, the resolve functions provide directions to convert GraphQL operations into data.

The GraphQL client#

The GraphQL client is the actual front-end component that allows us to accept queries, connect to the GraphQL endpoint, and issue queries to gather data. It may be a single-page application, a content management system (CMS), a mobile application, and so on.

GraphQL server and client components
GraphQL server and client components

Data manipulation using GraphQL#

GraphQL offers us two types of operations: queries and mutations. We have seen how data can be fetched using queries. However, there is also a need to have a mechanism to manipulate data on the server side. GraphQL uses operations called mutations in order to insert new data or modify the existing data on the server. We can think of GraphQL mutations as the equivalent of POST, PUT, PATCH, and DELETE methods used by REST.

GraphQL mutations#

Mutations in GraphQL are defined in a similar way as we define functions; in other words, mutations also have names and selection criteria. There are three types of GraphQL mutation operations.

  • Insert mutations: These are used to insert a new record on the server side.

  • Update mutations: These are used to modify an existing record in the database.

  • Delete mutations: These are used to delete a specific record from the database.

Let's insert a new record into the database using an insert mutation.

Assume that we have students' data stored in the database, including name, rollNo, and degreeProgram. The following mutation will insert a new student into the database after specifying values for name, rollNo, and degreeProgram. The AddNewStudent schema is defined on the server side, while addStudent is the function that a client can use to insert data in the database.

A GraphQL mutation to add a new student to the database

GraphQL request and response format#

A GraphQL query requests only the data that is needed. A query is defined using the word query, and inside it, we mention other objects and the attributes whose values need to be fetched.

Following is a GraphQL query requesting the attributes name, length, and cargoCapacity of the object starship having an ID equal to 10.

A GraphQL query for the Star Wars API (SWAPI)

The response to the preceding GraphQL query is in JSON format that matches the shape of our query, shown below. The response consists of the data we requested and has returned the name: Millennium Falcon, length: 34.37, and cargoCapacity: 100000 .

The response of the GraphQL query

GraphQL queries can be nested—for example, let's modify the query above and request the name, diameter, and climates of a planet having an ID equal to 5.

A modified GraphQL query requesting more data along with the previous query

In the query above, we are now requesting more information about another object that is a planet having an ID equal to 5. An advantage of the GraphQL query is that we can request different types of data within a single request. The following response now consists of the starship as well as the planet data.

The response of the modified GraphQL query

How does GraphQL fill the gaps in REST?#

GraphQL resolves both the shortcomings of the REST API in the following ways:

  • Multiple requests problem: GraphQL allows us to access multiple endpoints in a single query, which eliminates the first problem in the REST API. The following example shows a query accessing starship, planet, and allFilms data in a single request. So instead of sending multiple requests using the REST API, GraphQL does the job in a single query.

A single GraphQL query to access the starship, planet, and allFilms endpoints
  • Overfetching and underfetching: Similarly, a single GraphQL query also addresses the overfetching and the underfetching problem by accessing the exact information needed for an application. In the example above, we require some specific attribute values, and the response to the query only contains the values of the starship, planet, and allFilms, as shown below:

Values of some specific attributes of starship, planet, and allFilms fetched via a single GraphQL query

Point to Ponder

Question 2

If it is possible to fetch only the desired information using the REST API, then why is there a need for GraphQL?

Hide Answer

The partial response strategy, or filtering, is a flexible approach to getting the required information via REST APIs from a single endpoint. However, GraphQL benefits us the most in a case when we frequently need to retrieve desired responses from multiple endpoints at the same time.

2 of 2

GraphQL drawbacks#

Apart from the features that GraphQL provides, there are certain areas for improvement. For instance, it’s more complicated to implement than REST and incurs extra complexities. From a maintenance perspective, there are three main drawbacks when opting for GraphQL:

  • Error handling: REST provides us with a comprehensive response status that tells us about any error that occurred. In GraphQL, we need to parse the response to understand the error, which increases complexity and adds to user-perceived latency.

  • File upload: GraphQL specification does not include file uploads. This functionality is left to the developers and their choice of implementation, which includes one of the following strategies. These strategies are more complicated than the features REST provides:

    • Using a mutation with the Base64 encoded blobs, which makes the request larger and more complex to encode and decode.

    • Allocating dedicated servers or REST APIs to upload the files.

    • Using third-party libraries, such as graphql-upload.

  • Web caching: GraphQL can work with multiple endpoints; therefore, caching data at different levels is a bit harder.

Summary#

In this lesson, we explored GraphQL and the gaps it fills in REST. It provides a remedy for problems with underfetching and overfetching in the REST API. It also enables targeting multiple endpoints in a single request that reduces the round trips between clients and servers. GraphQL can look more beneficial than REST, but GraphQL also comes with certain drawbacks and complexities. For example, error handling, file uploading, and web caching are more complicated in GraphQL than in REST.

RESTful API

The gRPC Framework